package GUI;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.util.Iterator;

import javax.swing.Box;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;

import Plants.PowerPlant;
import Plants.PowerPlantListener;
import SmartGrid.ExecutionEngine;
import SmartGrid.SmartGrid;
import Tools.Library;
import Tools.Log;
import Tools.SmartGridStatus;

public class MainWindow extends JFrame{

	Box canvasBox;  //holds the energy grid canvas
	Box statusBox;  //holds a console where information is printed
	JTextPane status;  //displays information about the grid
	Box consoleBox;
	JTextField console;
	
	JMenuBar mainMenu;
	
	SmartGrid smartgrid;
	
	public MainWindow(SmartGrid smartgrid)
	{
		super("Stanford Energy Grid");
		initFrameProperties();
		addMainMenu();
		
		this.smartgrid = smartgrid;
		
		//Create and add the energy grid canvas
		canvasBox = Box.createHorizontalBox();
		canvasBox.setPreferredSize(new Dimension(Tools.Options.CANVAS_WIDTH, Tools.Options.CANVAS_HEIGHT));
		EnergyGridCanvas canvas = new EnergyGridCanvas(smartgrid);
		canvasBox.add(canvas);
		super.add(canvasBox, BorderLayout.NORTH);
		
		//Create and add the status box
		initStatusBox();
		initConsole();
		
		super.pack();
		super.setVisible(true);
	}
	
	private void initFrameProperties()
	{
		super.setLayout(new BorderLayout(4,4));
		super.setPreferredSize(new Dimension(Tools.Options.MAIN_WINDOW_WIDTH, Tools.Options.MAIN_WINDOW_HEIGHT));
		super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		super.addWindowListener(new WindowAdapter(){

			@Override
			public void windowClosing(WindowEvent arg0) {
				Log.Close();				
			}
			
		});
	}
	
	private String showFileChooser(boolean save)
	{
		JFileChooser fileChooser = new JFileChooser();
		fileChooser.setCurrentDirectory(new File("."));
		int returnVal;
		if(save)
			returnVal = fileChooser.showSaveDialog(this);
		else
			returnVal = fileChooser.showOpenDialog(this);
	    if (returnVal == JFileChooser.APPROVE_OPTION) 
	    {
	        java.io.File file = fileChooser.getSelectedFile();
	        return file.getAbsolutePath();
	    }
		return null;
	}
	
	private void addMainMenu()
	{
		mainMenu = new JMenuBar();
		JMenu file = new JMenu("File");
		JMenu status = new JMenu("Status");
		JMenuItem saveStatus = new JMenuItem("Save Grid Status");
		saveStatus.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				ExecutionEngine.pauseAllTasks();
				String filename = showFileChooser(true);
				if(filename != null)
					SmartGridStatus.saveGridStatus(smartgrid, filename);
				ExecutionEngine.resumeAllTasks();
			}
			
		});
		JMenuItem loadStatus = new JMenuItem("Load Grid Status");
		loadStatus.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				ExecutionEngine.pauseAllTasks();
				String filename = showFileChooser(false);
				if(filename != null)
					SmartGridStatus.loadGridStatus(smartgrid, filename);
				ExecutionEngine.resumeAllTasks();
			}
			
		});
		status.add(saveStatus);
		status.add(loadStatus);
		JMenu action = new JMenu("Action");
		JMenuItem pause = new JMenuItem("Pause Simulation");
		pause.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				ExecutionEngine.pauseAllTasks();
			}
			
		});
		JMenuItem resume = new JMenuItem("Resume Simulation");
		resume.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				ExecutionEngine.resumeAllTasks();
			}
			
		});
		action.add(pause);
		action.add(resume);
		mainMenu.add(file);
		mainMenu.add(status);
		mainMenu.add(action);
		super.setJMenuBar(mainMenu);
	}
	
	/**
	 * Receives updates from power plants about changes in supply and demand
	 */
	private void initStatusBox()
	{
		statusBox = Box.createHorizontalBox();
		statusBox.setPreferredSize(new Dimension(Tools.Options.STATUS_WIDTH, Tools.Options.STATUS_HEIGHT));
		status = new JTextPane();
		JScrollPane scroll = new JScrollPane(status);
		scroll.setPreferredSize(new Dimension(800,150));
		Iterator<PowerPlant> plants = smartgrid.allPlants.values().iterator();
		while(plants.hasNext())
		{
			PowerPlant plant = plants.next();
			plant.getListeners().add(new PowerPlantListener()
			{

				@Override
				public synchronized void PowerPlantResponsibilitiesChanged(PowerPlant p) {
					Library.appendToJTP(status, Color.BLACK, p.getName() + " Responsibilities Changed: " + p.getResponsibilities() + "\n");
			        Runnable scrollRectToVisibleMethod = new Runnable()
				    {
				        public void run ()
				        {
				        	status.scrollRectToVisible (new Rectangle(0,status.getHeight() - 2,1,1));
				        }
			        };
			        SwingUtilities.invokeLater (scrollRectToVisibleMethod);
				}

				@Override
				public synchronized void PowerPlantSupplyChanged(PowerPlant p) {
					Library.appendToJTP(status, Color.BLACK, p.getName() + " Supply Changed: " + p.getAvailableEnergy() + "\n");
			        Runnable scrollRectToVisibleMethod = new Runnable()
				    {
				        public void run ()
				        {
				        	status.scrollRectToVisible (new Rectangle(0,status.getHeight() - 2,1,1));
				        }
			        };
			        SwingUtilities.invokeLater (scrollRectToVisibleMethod);
				}

				@Override
				public void PowerPlantRepaint(PowerPlant p) {
					
				}
				
			});
		}
		statusBox.add(scroll);
		super.add(statusBox, BorderLayout.CENTER);
	}
	
	private void initConsole()
	{
		consoleBox = Box.createHorizontalBox();
		console = new JTextField();
		console.addActionListener(new ConsoleInterpreter(this));
		consoleBox.add(console);
		super.add(consoleBox, BorderLayout.SOUTH);
	}
	
	public JTextPane getStatus() {
		return status;
	}

	public JTextField getConsole() {
		return console;
	}

	public SmartGrid getSmartgrid() {
		return smartgrid;
	}	
	
}
